//Story 是一个讲故事的模块，他能动画显示文字和图片
import { tt } from "../../ttapi_interface/ttapi.js";
import * as tt2 from "../../ttapi_layer2/ttlayer2.js";
import { QFrame_Scene, QFrame_SceneObj } from "../../ttapi_layer2/ttlayer2.js";
import { UserData } from "../game.js";

enum StroyPos {
    Center,
}
class TimeLine {
    id: number;
    time: number;
    img: string
    text: string;
    pos: string;
    fadein: string;
    fadeintime: number;
    livetime: number;//存活时间， fadein 和fade out 之间的时间，-1 表示永久，0表示0
    fadeout: string;
    fadeouttime: number;
}
class TimeState {
    line: TimeLine;
    timer: number;
    finish: boolean;
}
class ItemInst {
    line: TimeLine;
    img: tt.Sprite;
    ui: tt2.QUI_BaseElement;
    height: number;
    endy: number;//
    constructor(line: TimeLine) {
        this.line = line;
    }
    async LoadAsync(): Promise<void> {
        if (this.line.img != undefined) {
            this.img = await tt2.QFrame_ResMgr.LoadStandaloneSpriteAsync(this.line.img);
        }
    }
    Show(scene: tt2.QFrame_IScene) {
        if (this.img != null) {
            this.ui = new tt2.QUI_Image(this.img);
            scene.GetUI().addChild(this.ui);
            let centery = scene.GetUI().getWorldRect().Height / 2;
            this.height = this.img.totalHeight;
            this.endy = centery - this.img.totalHeight / 2
            if (this.line.fadein == "moveup") {
                this.ui.localRect.setHPosByCenter(this.img.totalWidth);
                this.ui.localRect.setVPosByBottomBorder(this.img.totalHeight, -this.height);
            }
            else if (this.line.fadein == "alpha") {
                this.ui.localRect.setHPosByCenter(this.img.totalWidth);

                this.ui.localRect.setVPosByBottomBorder(this.img.totalHeight, this.endy);
            }
            else {
                throw new Error("unknonw fade mode:" + this.line.fadein)
            }
        }
        else {
            this.ui = new tt2.QUI_Label(scene.GetFont(), this.line.text);
            scene.GetUI().addChild(this.ui);
            let centery = scene.GetUI().getWorldRect().Height / 2;
            this.height = 20;
            this.endy = centery - 20 / 2
            this.ui.localRect.setHPosFill();
            if (this.line.fadein == "moveup") {
                this.ui.localRect.setVPosByBottomBorder(20, - this.height);
            }
            else if (this.line.fadein == "alpha") {
                this.ui.localRect.setVPosByBottomBorder(20, this.endy);
            }
            else {
                throw new Error("unknonw fade mode:" + this.line.fadein)
            }
        }
    }
    Destory() {
        if (this.ui != null) {
            this.ui._parent.removeChild(this.ui);
            this.ui = null;
        }
    }
    PlayFadeIn(timer: number) {
        if (this.line.fadein == "moveup") {
            let beginy = -this.height;

            let lerp = timer / this.line.fadeintime;
            if (lerp < 0) lerp = 0;
            if (lerp > 1) lerp = 1;
            let y = this.endy * lerp + beginy * (1 - lerp);
            this.ui.localRect.setVPosByBottomBorder(this.height, y);
        }
        else if (this.line.fadein == "alpha") {
            let lerp = timer / this.line.fadeintime;
            if (lerp < 0) lerp = 0;
            if (lerp > 1) lerp = 1;
            this.ui.alpha = lerp;
        }
        else {
            throw new Error("unknonw fade mode:" + this.line.fadein)
        }
    }
    PlayFadeOut(timer: number) {
        if (this.line.fadeout == "moveup") {

            let beginy = this.endy;
            let endy = this.endy + this.endy + this.height;

            let lerp = timer / this.line.fadeintime;
            if (lerp < 0) lerp = 0;
            if (lerp > 1) lerp = 1;
            let y = endy * lerp + beginy * (1 - lerp)
            this.ui.localRect.setVPosByBottomBorder(this.height, y);
        }
        else if (this.line.fadeout == "alpha") {
            let lerp = timer / this.line.fadeintime;
            if (lerp < 0) lerp = 0;
            if (lerp > 1) lerp = 1;

            this.ui.alpha = 1.0 - lerp;
        }
        else {
            throw new Error("unknonw fade mode:" + this.line.fadein)
        }
    }
}
export class Story {
    scene: QFrame_Scene<UserData>;
    timer: number;
    constructor(scene: QFrame_Scene<UserData>) {
        this.scene = scene;
        this.timer = 0;
    }
    OnUpdate(delta: number): void {
        this.timer += delta;

        //开始播放ppt
        for (var i = this.timeline.length - 1; i >= 0; i--) {
            var line = this.timeline[i];
            if (this.timer >= line.time) {
                this.timeline.splice(i, 1);
                this.activeItems.push({ line: line, finish: false, timer: 0 });
                this.InitItem(line);
                continue;
            }
        }

        //处理ppt动画
        for (var i = this.activeItems.length - 1; i >= 0; i--) {
            var item = this.activeItems[i];
            item.timer += delta;

            if (item.timer > item.line.fadeintime) {
                //live
                if (item.line.livetime != -1) {
                    //活够了
                    if (item.timer - item.line.fadeintime > item.line.livetime) {
                        item.timer = 0;
                        this.fadeoutItems.push(item);
                        this.activeItems.splice(i, 1);

                        continue;
                    }
                }

            }
            else {//fadein
                this.PlayFadeIn(item.line, item.timer);
            }
        }

        for (var i = this.fadeoutItems.length - 1; i >= 0; i--) {
            var item = this.fadeoutItems[i];
            item.timer += delta;
            if (item.timer > item.line.fadeouttime) {
                //活够了
                this.fadeoutItems.splice(i, 1);
                this.DestoryItem(item.line);
                continue;
            }
            else {
                this.PlayFadeOut(item.line, item.timer);
            }
        }
    }
    //private _finish = false;
    private _allfadeout = false;
    IsFinish(): boolean {
        if (this.timeline.length > 0)
            return false;
        for (var i = 0; i < this.activeItems.length; i++) {
            if (this.activeItems[i].line.livetime != -1)
                return false;
        }
        return true;
    }
    IsAllFadeOut(): boolean {
        if (this.timeline.length > 0)
            return false;
        if (this.activeItems.length > 0)
            return false;
        if (this.fadeoutItems.length > 0)
            return false;
        return true;

    }
    FadeOutAll(): number {
        if (!this.IsFinish()) {
            throw new Error("must call this after finish.");
        }
        let outtimer = 0;
        for (var i = 0; i < this.activeItems.length; i++) {
            let item = this.activeItems[i];
            item.timer = 0;
            if (outtimer < item.line.fadeouttime) {
                outtimer = item.line.fadeouttime;
            }
            this.fadeoutItems.push(item);
        }
        this.activeItems.splice(0);
        return outtimer;
    }
    Destory(): void {
        for (var i in this.iteminst) {
            this.iteminst[i].Destory();
        }

    }
    timeline: TimeLine[] = [];
    activeItems: TimeState[] = [];
    fadeoutItems: TimeState[] = [];
    async LoadAsync(jsonurl: string): Promise<void> {
        let txt = await tt.loader.LoadStringAsync(tt2.QFrame_ResMgr.GetDefResPath() + jsonurl);
        let story = JSON.parse(txt);

        this.timeline = story.timeline;
        for (var i = 0; i < this.timeline.length; i++) {
            this.timeline[i].id = i;
            let inst = this.iteminst[i] = new ItemInst(this.timeline[i]);
            await inst.LoadAsync();
        }
    }

    iteminst: { [id: number]: ItemInst } = {}
    private InitItem(line: TimeLine) {
        let inst = this.iteminst[line.id];
        inst.Show(this.scene);
    }
    private DestoryItem(line: TimeLine) {
        let inst = this.iteminst[line.id];
        inst.Destory();
    }
    private PlayFadeIn(line: TimeLine, timer: number) {
        let inst = this.iteminst[line.id];
        inst.PlayFadeIn(timer);
    }
    private PlayFadeOut(line: TimeLine, timer: number) {
        let inst = this.iteminst[line.id];
        inst.PlayFadeOut(timer);
    }
}